package ac.github.os.internal.core.action.player

import ac.github.os.internal.core.action.IEntityAction
import ac.github.os.internal.core.config.StringConfig
import ac.github.os.internal.core.config.get
import ac.github.os.internal.session.Cache
import ac.github.os.internal.session.Session
import org.bukkit.entity.Player
import org.bukkit.inventory.Inventory
import org.bukkit.inventory.ItemStack
import taboolib.common.platform.Awake
import taboolib.common5.Coerce
import taboolib.library.xseries.XMaterial
import taboolib.type.BukkitEquipment
import java.util.*

abstract class ItemAction(val name: String) : IEntityAction {
    override fun onExecute(session: Session, cache: Cache, config: StringConfig) {
        cache.filterIsPlayers().forEach { _ -> this.run(session, cache, config) }
    }

    fun StringConfig.slot() = get<String>("slot")?.uppercase(Locale.getDefault())

    abstract fun run(session: Session, cache: Cache, config: StringConfig)

    override val namespace: String
        get() = "item:$name"

    fun getItem(player: Player, slot: String): ItemStack? {
        return player.inventory.getItem(getSlot(player, slot))
    }

    fun getSlot(player: Player, slot: String): Int {
        val bukkitEquipment = BukkitEquipment.fromString(slot)
        return if (bukkitEquipment != null) {
            if (bukkitEquipment === BukkitEquipment.HAND) player.inventory.heldItemSlot else bukkitEquipment.slot
        } else {
            Coerce.asInteger(slot).get()
        }
    }

    fun setItem(player: Player, slot: String, itemStack: ItemStack) {
        player.inventory.setItem(getSlot(player, slot), itemStack)
    }

}

@Awake
class ItemRemoveAction : ItemAction("remove") {
    override fun run(session: Session, cache: Cache, config: StringConfig) {

        val amount = config.get<Int>("amount")
        val update = config.get("update", false)!!
        val slot = config.slot()!!

        cache.filterIsPlayers().forEach {
            getItem(it, slot)?.apply {
                this.amount = this.amount - (amount ?: this.amount)
                if (update) {
                    setItem(it, slot, this)
                }
            }
        }
    }
}